<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    // ES6 允许按照一定模式 从数组和对象中提取值 对变量进行赋值 被称为解构 Destructuring
    // 以前
    let a = 1;
    let b = 2;
    // 现在 ES6允许这样写
    let [a, b] = [1, 2];

    // 可以从数组中提取值 按照对应位置对变量赋值

    // 一些例子
    let [foo, [[bar], baz]] = [1, [[2], 3]];
    foo // 1
    bar // 2
    baz // 3

    let [ , , third] = ["foo", "bar", "baz"];
    third // "baz"

    let [x, , y] = [1, 2, 3];
    x // 1
    y // 3

    let [head, ...tail] = [1, 2, 3, 4];
    head // 1
    tail // [2, 3, 4]

    let [x, y, ...z] = ['a'];
    x // "a"
    y // undefined
    z // []

    // 如果解构不成功 就返回undefined foo的值都等于undefined
    let [foo] = [];
    let [bar, foo] = [1];

    // 不完全解构是可以成功的
    let [x, y] = [1, 2, 3];
    x // 1
    y // 2

    let [a, [b], d] = [1, [2, 3], 4];
    a // 1
    b // 2
    d // 4

    // 如果等号右边不是数组或者不是可遍历的结构 将会报错
    // 报错
    let [foo] = 1;
    let [foo] = false;
    let [foo] = NaN;
    let [foo] = undefined;
    let [foo] = null;
    let [foo] = {};

    // 事实上，只要某种数据结构具有 Iterator 接口，都可以采用数组形式的解构赋值。


    // 解构赋值允许默认值
    let [foo = true] = [];
    foo // true
    let [x, y = 'b'] = ['a']; // x='a', y='b'
    let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

    // ES6 内部使用严格相等运算符（===）判断一个位置是否有值
    // 只有当一个数组成员严格等于undefined，默认值才会生效
    let [x = 1] = [undefined];
    x // 1

    let [x = 1] = [null];
    x // null    null不严格等于undefined 默认值不生效

    // 如果默认值是一个表达式，那么这个表达式是惰性求值的，即只有在用到的时候，才会求值。
    function f() {
        console.log('aaa');
    }

    let [x = f()] = [1];

    // 默认值可以引用解构赋值的其他变量，但该变量必须已经声明。
    let [x = 1, y = x] = [];     // x=1; y=1
    let [x = 1, y = x] = [2];    // x=2; y=2
    let [x = 1, y = x] = [1, 2]; // x=1; y=2
    let [x = y, y = 1] = [];     // ReferenceError: y is not defined

    
</script>